package com.fs.util;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * Created by fengshuai on 17/5/18.
 */
public class DateUtil {
    private static Logger logger = Logger.getLogger(DateUtil.class);

    public final static String DefaultShortFormat = "yyyy-MM-dd";
    public final static String DefaultLongFormat = "yyyy-MM-dd HH:mm:ss";
    public final static String DefaultMinuteFormat = "yyyy-MM-dd HH:mm";


    /**
     * the string format must yyyy-MM-dd
     *
     * @param str
     * @return
     * @author zhaolei
     * <p/>
     * 2011-4-21
     */
    public static Date string2DateDay(String str) {
        DateTimeFormatter formatter = ISODateTimeFormat.date();
        DateTime dateTime = formatter.parseDateTime(str);
        return dateTime.toDate();
    }


    public static int string2Unixtime(String str) {
        Date date = string2DateDay(str);
        return date2Unixtime(date);
    }


    /**
     * the string format must yyyy-MM-dd HH:mm
     *
     * @param str
     * @return
     * @author zhaolei
     * <p/>
     * 2011-4-21
     */
    public static Date stirng2DateMinute(String str) {
        return string2Date4Null(str, DefaultMinuteFormat);
    }


    /**
     * 字符串转日期.如果异常则返回null
     *
     * @param str          日期字符串
     * @param formatString 格式化的格式代码 yyyy MM dd HH mm ss
     * @return
     * @author zhaolei
     * @created 2011-10-26
     */
    public static Date string2Date4Null(String str, String formatString) {
        String str2 = StringUtils.trimToEmpty(str);
        DateTimeFormatter formatter = DateTimeFormat.forPattern(formatString);
        return formatter.parseDateTime(str2).toDate();
    }

    public static Date string2Date4Null(String str) {
        return string2Date4Null(str, DefaultShortFormat);
    }

    /**
     * yyyy-MM-dd
     *
     * @param date
     * @return
     * @author zhaolei
     * <p/>
     * 2011-4-21
     */
    public static String Date2String(Date date) {
        return Date2String(date, DefaultShortFormat);
    }

    /**
     * yyyyMMdd
     *
     * @param date
     * @return
     * @author liuhujun
     * <p/>
     * 2012-3-28
     */
    public static Integer Date2IntDay(Date date) {
        DateTime dateTime = new DateTime(date);
        DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyyMMdd");
        return Integer.valueOf(dateTime.toString(formatter));
    }

    /**
     * 秒转日期
     *
     * @param seconds
     * @return
     */
    public static String secondsToString(Integer seconds) {
        return Date2String(fromUnixTime(seconds));
    }

    public static String secondsToString(Long seconds) {
        return Date2String(fromUnixTime(seconds));
    }

    /**
     * @param date
     * @return yyyy-MM-dd HH:mm的字符串
     */
    public static String Date2StringMin(Date date) {
        DateTime dateTime = new DateTime(date);
        DateTimeFormatter formatter = DateTimeFormat.forPattern(DefaultMinuteFormat);
        return dateTime.toString(formatter);
    }

    /**
     * @param date
     * @return yyyy-MM-dd HH:mm:ss的字符串
     */
    public static String Date2StringSec(Date date) {
        DateTime dateTime = new DateTime(date);
        DateTimeFormatter formatter = DateTimeFormat.forPattern(DefaultLongFormat);
        return dateTime.toString(formatter);
    }

    /**
     * @param seconds
     * @return 当前时间的秒数
     */
    public static String Date2StringSec(Integer seconds) {
        return Date2StringSec(fromUnixTime(seconds));
    }

    /**
     * must yyyy MM dd HH mm ss
     *
     * @param date
     * @param formatString
     * @return
     * @author zhaolei
     * <p/>
     * 2011-4-21
     */
    public static String Date2String(Date date, String formatString) {
        return seconds2TimeFormat(date.getTime() / 1000, formatString);
    }

    /**
     * 将秒数转换为指定格式的时间字符串
     *
     * @param time   以秒计时间
     * @param format 制定格式
     * @return 制定格式的时间string
     * @author yuanguangqiang
     * 2015-01-15
     */
    public static String seconds2TimeFormat(long time, String format) {
        try {
            DateTimeFormatter formatter = DateTimeFormat.forPattern(format);
            return formatter.print(time * 1000);//乘1000变毫秒
        } catch (IllegalArgumentException e) {
            logger.error("format string failed :format=" + format + ",time=" + time, e);
            return "";
        }
    }

    /**
     * 将指定格式的时间字符串转换为秒数
     *
     * @param timeStr 固定格式时间,可选三种格式
     * @return 秒数
     * @author yuanguangqiang
     * 2015-01-15
     */
    public static long parseTimeStr2Seconds(String timeStr) {
        List<DateTimeFormatter> formatterList = getDateTimeFormatter();

        for (DateTimeFormatter formatter : formatterList) {
            DateTime dateTime = parseTimeStrToDate(timeStr, formatter);
            if (dateTime != null) {
                return dateTime.getMillis() / 1000;
            }
        }
        return 0l;
    }

    public static List<DateTimeFormatter> getDateTimeFormatter() {
        List<DateTimeFormatter> list = new ArrayList<DateTimeFormatter>();
        list.add(DateTimeFormat.forPattern(DefaultLongFormat));
        list.add(DateTimeFormat.forPattern(DefaultMinuteFormat));
        list.add(DateTimeFormat.forPattern(DefaultShortFormat));
        list.add(DateTimeFormat.forPattern("yyyyMMdd HH:mm:ss"));
        list.add(DateTimeFormat.forPattern("yyyyMMdd HH:mm"));
        list.add(DateTimeFormat.forPattern("yyyyMMdd"));
        return list;
    }

    private static DateTime parseTimeStrToDate(String timeStr, DateTimeFormatter format) {
        try {
            return format.parseDateTime(timeStr);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 返回当前时间的秒数
     *
     * @return
     */
    public static int unixTime() {
        return (int) (System.currentTimeMillis() / 1000);
    }

    /**
     * 把表转换为Date
     *
     * @param seconds
     * @return
     */
    public static Date fromUnixTime(Integer seconds) {
        return new Date(seconds * 1000L);
    }

    public static Date fromUnixTime(Long seconds) {
        return new Date(seconds * 1000L);
    }

    /**
     * @return
     */
    public static Date toDay() {
        return toDay(new Date());
    }

    public static Date toDay(Date date) {
        if (date == null) {
            date = new Date();
        }
        DateTime dateTime = new DateTime(date);
        DateTime toDateTime = new DateTime(dateTime.getYear(),
                dateTime.getMonthOfYear(), dateTime.getDayOfMonth(), 0, 0, 0);
        return toDateTime.toDate();
    }

    /**
     * 指定日期当天的最后一秒
     *
     * @param date
     * @return
     * @author lichengwu
     * @created Sep 13, 2011
     */
    public static Date toNight(Date date) {
        if (date == null) {
            date = new Date();
        }
        DateTime dateTime = new DateTime(date);
        DateTime nightDateTime = new DateTime(dateTime.getYear(),
                dateTime.getMonthOfYear(), dateTime.getDayOfMonth(), 23, 59, 59);
        return nightDateTime.toDate();
    }


    /**
     * 返回开始到结束时间所有的日期
     *
     * @param startDateStr （yyyy-MM-dd） 开始时间
     * @param endDateStr   （yyyy-MM-dd） 结束时间
     * @return
     */
    public static List<String> dateBetween(String startDateStr, String endDateStr) {
        List<String> dateList = new ArrayList<String>();
        DateTime startDateTime = new DateTime(startDateStr);
        DateTime endDateTime = new DateTime(endDateStr);
        while (startDateTime.compareTo(endDateTime) <= 0) {
            dateList.add(Date2String(startDateTime.toDate()));
            startDateTime = startDateTime.plusDays(1);
        }

        return dateList;
    }

    /**
     * 按照给定的日期格式，返回开始到结束时间所有的日期
     *
     * @param startDateStr （yyyy-MM-dd） 开始时间
     * @param endDateStr   （yyyy-MM-dd） 结束时间
     * @param formatString
     * @return
     */
    public static List<String> dateBetween(String startDateStr, String endDateStr, String formatString) {
        List<String> dateList = new ArrayList<String>();
        DateTime startDateTime = new DateTime(startDateStr);
        DateTime endDateTime = new DateTime(endDateStr);
        while (startDateTime.compareTo(endDateTime) <= 0) {
            dateList.add(Date2String(startDateTime.toDate(), formatString));
            startDateTime = startDateTime.plusDays(1);
        }

        return dateList;
    }

    /**
     * 将时间转换成昨天
     *
     * @param date
     * @return
     * @author lichengwu
     * @created 2011-11-1
     */
    public static Date toYesterday(Date date) {
        DateTime dateTime;
        if (date == null) {
            dateTime = DateTime.now();
        } else {
            dateTime = new DateTime(date);
        }
        dateTime = dateTime.minusDays(1);
        return dateTime.toDate();
    }

    /**
     * 将时间转换成明天
     *
     * @param date
     * @return
     * @author lichengwu
     * @created 2011-11-1
     */
    public static Date toTommorow(Date date) {
        DateTime dateTime;
        if (date == null) {
            dateTime = DateTime.now();
        } else {
            dateTime = new DateTime(date);
        }

        dateTime = dateTime.plusDays(1);
        return dateTime.toDate();
    }


    /**
     * 得到某年某月有多少天
     *
     * @param year
     * @param month
     * @return
     * @author zhaolei
     * @created 2011-11-1
     */
    public static int getMonthDays(int year, int month) {
        DateTime dateTime = new DateTime(year, month, 1, 0, 0, 0);
        return dateTime.dayOfMonth().getMaximumValue();
    }

    /**
     * 得到年份
     *
     * @param date
     * @return
     * @author zhaolei
     * @created 2011-11-8
     */
    public static int getYear(Date date) {
        DateTime dateTime;
        if (date == null) {
            dateTime = DateTime.now();
        } else {
            dateTime = new DateTime(date);
        }
        return dateTime.getYear();
    }

    /**
     * 得到月份
     *
     * @param date
     * @return
     * @author zhaolei
     * @created 2011-11-8
     */
    public static int getMonth(Date date) {
        DateTime dateTime;
        if (date == null) {
            dateTime = DateTime.now();
        } else {
            dateTime = new DateTime(date);
        }
        return dateTime.getMonthOfYear();
    }

    /**
     * 得到某天的星期.1~~7
     *
     * @param date
     * @return
     * @author zhaolei
     * @created 2011-11-9
     */
    public static int getDayOfWeek(Date date) {
        DateTime dateTime;
        if (date == null) {
            dateTime = DateTime.now();
        } else {
            dateTime = new DateTime(date);
        }
        return dateTime.getDayOfWeek();
    }

    /**
     * 日期（天）转unixtime
     *
     * @param day
     * @return
     * @author liuhujun
     * @created 2012-03-15
     */
    public static int day2Unixtime(String day) {
        return (int) (DateUtil.string2DateDay(day).getTime() / 1000L);
    }

    /**
     * date转unixtime
     *
     * @param date
     * @return
     * @author liuhujun
     * @created 2012-06-15
     */
    public static int date2Unixtime(Date date) {
        return (int) (date.getTime() / 1000L);
    }


    /**
     * 返回每周一的日期
     *
     * @param date
     * @return
     */
    public static Date getMondayDate(Date date) {
        DateTime dateTime;
        if (date == null) {
            dateTime = DateTime.now();
        } else {
            dateTime = new DateTime(date);
        }
        dateTime = dateTime.minusDays(dateTime.getDayOfWeek() - 1);
        return dateTime.toDate();
    }

    /**
     * 返回每周一的起始时间的时间戳
     *
     * @param dateStr
     * @return
     */
    public static Integer getMondayDate(String dateStr) {
        Date date = string2DateDay(dateStr);
        date = getMondayDate(date);
        return date2Unixtime(date);
    }


    /**
     * 获取本月的起始时间
     */
    public static long getThisMonthStart() {
        DateTime now = DateTime.now();
        DateTime dateTime = new DateTime(now.getYear(), now.getMonthOfYear(), 1, 0, 0, 0);
        return dateTime.getMillis() / 1000;
    }

    /**
     * 获取一周的开始日期
     *
     * @param date
     * @return
     */
    public static Date getFirstDayOfWeek(Date date) {
        DateTime dateTime;
        if (date == null) {
            dateTime = DateTime.now();
        } else {
            dateTime = new DateTime(date);
        }

        dateTime = dateTime.minusDays(dateTime.getDayOfWeek());
        return dateTime.toDate();
    }

    /**
     * 返回本周起始时间的时间戳
     *
     * @param dateStr
     * @return
     */
    public static Integer getFirstDayOfWeek(String dateStr) {
        Date date = string2DateDay(dateStr);
        date = getFirstDayOfWeek(date);
        return date2Unixtime(date);
    }

    /**
     * 本月的最后一天
     */
    public static int getLastDayOfMonth() {
        Calendar endCal = Calendar.getInstance();
        return endCal.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    public static int getTodayStartTime() {
        Calendar time = Calendar.getInstance();
        time.set(11, 0);
        time.set(12, 0);
        time.set(13, 0);
        return (int) (time.getTimeInMillis() / 1000L);
    }

    public static int getPastDate(int past) throws ParseException {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) - past);
        Date today = calendar.getTime();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String result = format.format(today);
        int time = (int) (format.parse(result).getTime() / 1000L);
        return time;
    }

    /**
     * 指定时间的前一天的开始时间
     *
     * @param unixtime
     * @return
     */
    public static int getDayStartOfTime(int unixtime) {
        Date date = new Date(unixtime * 1000L);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return (int) (calendar.getTimeInMillis() / 1000L);
    }

    public static String dateString2String(String dateString,String format) {
        Date date = string2Date4Null(dateString, format);
        return Date2String(date, DefaultShortFormat);
    }

    public static void main(String[] args) {
        System.out.println(dateString2String("20160519", "YYYYMMdd"));
    }
}
